package com.gopay.bis.service.bank.impl;

import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Service;

import com.gopay.bis.common.util.DateUtils;
import com.gopay.bis.service.bank.TpasOrderService;
import com.gopay.bis.service.bank.task.TpasChargeTaskThread;
import com.gopay.common.constants.bank.tpas.TpasInterfaceEnum;
import com.gopay.common.constants.bank.tpas.TpasMwaChargeConstants;
import com.gopay.common.constants.txncd.IntTxnCd;
import com.gopay.common.domain.bank.tpas.TpasMessage;
import com.gopay.common.domain.bank.tpas.TpasOrder;
import com.gopay.common.domain.bank.tpas.TpasResult;
import com.gopay.common.domain.bank.tpas.mwa.FlowMessage;
import com.gopay.common.domain.bank.tpas.mwa.MobileMessage;
import com.gopay.common.domain.bank.tpas.mwa.OilCardMessage;
import com.gopay.common.exception.GopayException;
import com.gopay.common.util.spring.SpringContextUtil;
import com.gopay.remote.bank.TpasChargeInteractRemoteService;

@Service("bisTpasChargeService")
public class BisTpasChargeServiceImpl implements TpasChargeInteractRemoteService {
	private static Logger logger = LoggerFactory.getLogger(BisTpasChargeServiceImpl.class);
    @Resource(name = "tpasChannCfg")
    private Map<String,String> tpasChannCfg;
    @Resource(name = "ofpayCfg")
    private Map<String,String> ofpayCfg;
	@Resource(name = "tpasOrderService")
    protected TpasOrderService tpasOrderService;
    
	@Autowired
	@Qualifier("taskExecutor")
	private TaskExecutor taskExecutor;

    @Override
    public TpasResult mobileBelong(TpasMessage base) throws GopayException {
        base.setInterfaceCode(TpasInterfaceEnum.MOBINFO);
        String beanName = getBeanName(base);
        TpasChargeInteractRemoteService bankService = (TpasChargeInteractRemoteService) SpringContextUtil.getBean(beanName);
        TpasResult mobileBelong = bankService.mobileBelong(base);
        logger.error("手机归属地查询返回对象" + ToStringBuilder.reflectionToString(mobileBelong.getDefaultModel(), ToStringStyle.DEFAULT_STYLE));
        return mobileBelong;
    }
    
    @Override
    public TpasResult mobileCharge(TpasMessage base) throws GopayException {
    	logger.error("手机充值处理base对象" + ToStringBuilder.reflectionToString(base, ToStringStyle.DEFAULT_STYLE));
        base.setInterfaceCode(TpasInterfaceEnum.MOBILECHARGE);
        MobileMessage msg = new MobileMessage();
        BeanUtils.copyProperties(base, msg);
        msg.setBankOrderId(base.getOrderId());
        msg.setCardId(ofpayCfg.get("CHARGETYPE"));
        msg.setOrderDate(DateUtils.date2string(new Date(), "yyyyMMddHHmmss"));
        String beanName = getBeanName(msg);
        TpasResult result = addOrder(msg);
        TpasChargeInteractRemoteService bankService = (TpasChargeInteractRemoteService) SpringContextUtil.getBean(beanName);
        charge(msg,bankService, tpasOrderService);
        return result;
    }

    @Override
    public TpasResult flowCharge(TpasMessage base) throws GopayException {
    	logger.error("流量充值处理base对象" + ToStringBuilder.reflectionToString(base, ToStringStyle.DEFAULT_STYLE));
        base.setInterfaceCode(TpasInterfaceEnum.FLOWCHARGE);
        FlowMessage msg = new FlowMessage();
        BeanUtils.copyProperties(base, msg);
        msg.setBankOrderId(base.getOrderId());
        msg.setOrderDate(DateUtils.date2string(new Date(), "yyyyMMddHHmmss"));
        String beanName = getBeanName(msg);
        TpasResult result = addOrder(msg);
        TpasChargeInteractRemoteService bankService = (TpasChargeInteractRemoteService) SpringContextUtil.getBean(beanName);
        charge(msg,bankService, tpasOrderService);
        return result;
    }
    
    @Override
    public TpasResult oilCardInfo(TpasMessage base) throws GopayException {
        base.setInterfaceCode(TpasInterfaceEnum.OILCARDINFO);
        OilCardMessage msg = new OilCardMessage();
        BeanUtils.copyProperties(base, msg);
        String beanName = getBeanName(msg);
        TpasChargeInteractRemoteService bankService = (TpasChargeInteractRemoteService) SpringContextUtil.getBean(beanName);
        TpasResult res = bankService.oilCardInfo(msg);
        OilCardMessage retmsg = (OilCardMessage) res.getDefaultModel();
        logger.error("加油卡信息查询返回对象" + ToStringBuilder.reflectionToString(retmsg, ToStringStyle.DEFAULT_STYLE));
        return res;
    }


    @Override
    public TpasResult oilCardCharge(TpasMessage base) throws GopayException {
    	logger.error("加油卡充值处理base对象" + ToStringBuilder.reflectionToString(base, ToStringStyle.DEFAULT_STYLE));
        base.setInterfaceCode(TpasInterfaceEnum.OILCARDCHARGE);
        OilCardMessage msg = new OilCardMessage();
        BeanUtils.copyProperties(base, msg);
        msg.setBankOrderId(base.getOrderId());
        msg.setOrderDate(DateUtils.date2string(new Date(), "yyyyMMddHHmmss"));
        String beanName = getBeanName(msg);
        TpasResult result = addOrder(msg);
        TpasChargeInteractRemoteService bankService = (TpasChargeInteractRemoteService) SpringContextUtil.getBean(beanName);
        charge(msg,bankService, tpasOrderService);
        return result;
    }
    @Override
    public TpasResult tpasBack(TpasMessage msg) throws GopayException {
        String orderId = msg.getOutOrderId();
        TpasResult result = new TpasResult();
		try {
			TpasOrder order = tpasOrderService.getTpasOrderByCpOrderId(orderId);
			String beanName = order.getIntrfaceChannelCode() + "-TPAS";
			TpasChargeInteractRemoteService tpasService = (TpasChargeInteractRemoteService) SpringContextUtil.getBean(beanName);
			result = tpasService.tpasBack(msg);
			result.setTransType(order.getProdCode());
			result.setOrderid(order.getOrderId());
			TpasMessage res = (TpasMessage)result.getDefaultModel();
			if (result.isSuccess() && TpasMwaChargeConstants.CHARGE_SUCCESS.equals(res.getRetCode())) {
			    // 充值成功
			    tpasOrderService.updateBackSuccess(order.getOrderId());
			    logger.error("充值订单【 "+beanName+"】返回处理结果：国付宝订单号【"+order.getOrderId()+"】充值成功，bis_tpas_main_order表更新成功状态");
			    
			}else if(result.isSuccess() && TpasMwaChargeConstants.CHARGE_FAIL.equals(res.getRetCode())){
			    // 充值失败
			    tpasOrderService.updateBackFail(order.getOrderId());
			    logger.error("银行【 "+beanName+"】返回处理结果：国付宝订单号【"+order.getOrderId()+"】充值失败，bis_tpas_main_order表更新失败状态");
			}
		} catch (BeansException e) {
			result.setSuccess(false);
			result.setErrorMsg("更新bis_tpas_main_order表异常，orderid="+msg.getOutOrderId());
			logger.error("更新bis_tpas_main_order表异常，orderid="+msg.getOutOrderId(), e);
		}
        return result;
    }
    
    private TpasResult addOrder(TpasMessage msg) throws GopayException {
        List<TpasOrder> tpasOrders = tpasOrderService.getTpasOrdersByGopayOrderId(msg.getOrderId());
        TpasResult result = new TpasResult();
        if(tpasOrders != null && tpasOrders.size() > 0){
        	logger.error("充值订单号重复 ! gopayOutOrderId=" + msg.getBankOrderId());
        	throw new GopayException("100E5013", "充值订单号重复 ! gopayOutOrderId=" + msg.getBankOrderId());
        }
        TpasOrder order = tpasOrderService.addOrder(msg);
        result.setSuccess(true);
        return result;    
    }

    @Override
    public TpasResult queryOrderStatus(TpasMessage base) throws GopayException {
        base.setInterfaceCode(TpasInterfaceEnum.QUERYCHARGESTATUS);
        base.setBankOrderId(base.getBankOrderId());
        String beanName = getBeanName(base);
        TpasChargeInteractRemoteService bankService = (TpasChargeInteractRemoteService) SpringContextUtil.getBean(beanName);
        TpasResult res = bankService.queryOrderStatus(base);
        return res;
    }

    private String getBeanName(TpasMessage base) {
        TpasInterfaceEnum interfaceCode = base.getInterfaceCode();
        String channName = "";
        if(TpasInterfaceEnum.MOBINFO.equals(interfaceCode) || TpasInterfaceEnum.QUERYCHARGESTATUS.equals(interfaceCode)){
            String transType = base.getTransType();
            if(IntTxnCd._01611.value.equals(transType))
                channName = tpasChannCfg.get(TpasInterfaceEnum.MOBILECHARGE.getValue());
            else if(IntTxnCd._01612.value.equals(transType))
                channName = tpasChannCfg.get(TpasInterfaceEnum.FLOWCHARGE.getValue()); 
            else if(IntTxnCd._01613.value.equals(transType))
                channName = tpasChannCfg.get(TpasInterfaceEnum.OILCARDCHARGE.getValue()); 
        }
        else if(TpasInterfaceEnum.MOBILECHARGE.equals(interfaceCode)){
            channName = tpasChannCfg.get(TpasInterfaceEnum.MOBILECHARGE.getValue());
        }else if(TpasInterfaceEnum.FLOWCHARGE.equals(interfaceCode)){
            channName = tpasChannCfg.get(TpasInterfaceEnum.FLOWCHARGE.getValue());
        }else if(TpasInterfaceEnum.OILCARDINFO.equals(interfaceCode) || TpasInterfaceEnum.OILCARDCHARGE.equals(interfaceCode)){
            channName = tpasChannCfg.get(TpasInterfaceEnum.OILCARDCHARGE.getValue());
        }
        base.setOutStlmCd(channName);
        setSpAccountAndSpPwd(channName, base);
        return channName + "-TPAS";
    }
    private void setSpAccountAndSpPwd(String channName, TpasMessage base) {
        if("OFPAY".equals(channName)){
            base.setMerID(ofpayCfg.get("OFPAYACC"));
            base.setPrivatePwd(ofpayCfg.get("OFPAYPWD"));
            base.setPrivatePwd2nd(ofpayCfg.get("OFPAYPWD2ND"));
            base.setVersion(ofpayCfg.get("VERSION"));
        }
    }
    
    private void charge(TpasMessage msg, TpasChargeInteractRemoteService bankService, TpasOrderService tpasOrderService) throws GopayException {
		TpasChargeTaskThread thread = new TpasChargeTaskThread(msg,bankService, tpasOrderService);
		taskExecutor.execute(thread);
	}
}
